﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;

namespace Microsoft.AspNetCore.App.Http
{
    public class Kestrel
    {
        private readonly ILogger _logger;
        private readonly KestrelOptions _options;
        private readonly IServiceProvider _serviceProvider;
        private readonly IApplicationBuilder _applicationBuilder;

        public Kestrel(
            ILogger<Kestrel> logger,
            IOptions<KestrelOptions> options,
            IServiceProvider serviceProvider,
            IApplicationBuilder applicationBuilder)
        {
            _logger = logger;
            _options = options.Value;
            _serviceProvider = serviceProvider;
            _applicationBuilder = applicationBuilder;
        }

        public void Start(string url)
        {
            var uri = new Uri(url);
            var serverSocket = new Socket(
                AddressFamily.InterNetwork,
                SocketType.Stream,
                ProtocolType.Tcp);
            var address = IPAddress.Parse(uri.Host);
            //绑定端口
            serverSocket.Bind(new IPEndPoint(address, uri.Port));
            serverSocket.Listen(100);
            //构建管道
            var pipeline = _applicationBuilder.Build();
            new Thread(() =>
            {
                while (true)
                {
                    //这里会阻塞，因此启动一个线程来处理
                    var clientSocket = serverSocket.Accept();
                    new Thread(() => 
                    {
                        try
                        {
                             AcceptRequestAsync(clientSocket, pipeline).GetAwaiter().GetResult();
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, ex.Message);
                        }
                    }).Start();
                }
            }).Start();
        }

        public async Task AcceptRequestAsync(Socket socket, RequestDelegate pipeline)
        {
            //接收客户端请求
            var buffer = new byte[_options.MaxRequestBufferSize];
            var count = socket.Receive(buffer);
            var content = Encoding.UTF8.GetString(buffer, 0, count);
            //json-http
            var request = JsonSerializer.Deserialize<HttpRequest>(content);
            if (request == null)
            {
                throw new InvalidOperationException("无效的请求");
            }
            try
            {
                //请求的容器范围
                using (var scope = _serviceProvider.CreateScope())
                {
                    //使用子容器
                    var context = new HttpContext(request, scope.ServiceProvider);
                    //使用管道来处理http上下文
                    await pipeline(context);
                    var bytes = context.Response.GeteBuffer();
                    //相应数据会客户端
                    socket.Send(bytes);
                }
            }
            finally 
            { 
                socket.Close();
            }
        }
    }
}
